package ac.github.oa.internal.core.ui

import ac.github.oa.api.event.item.ItemDecomposeEvent
import ac.github.oa.internal.core.item.ItemPlant
import ac.github.oa.internal.core.ui.Decompose.confirm
import ac.github.oa.internal.core.ui.Decompose.confirmIcon
import ac.github.oa.internal.core.ui.Decompose.default
import ac.github.oa.internal.core.ui.Decompose.getIcon
import ac.github.oa.internal.core.ui.Decompose.show
import ac.github.oa.internal.core.ui.Decompose.slot
import org.bukkit.entity.Player
import org.bukkit.event.inventory.ClickType
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.ItemStack
import taboolib.common.util.random
import taboolib.library.xseries.getItemStack
import taboolib.module.chat.colored
import taboolib.module.nms.getItemTag
import taboolib.module.ui.buildMenu
import taboolib.module.ui.type.Basic
import taboolib.platform.util.buildItem
import taboolib.platform.util.giveItem
import taboolib.platform.util.isAir
import taboolib.platform.util.sendLang

class DecomposeUI(val viewer: Player) {

    val decomposeItems = mutableListOf<ItemStack>()

    var get = false

    fun open() {
        viewer.openInventory(build())
    }

    fun build() : Inventory {
        return buildMenu<Basic>(Decompose.title.colored()) {
            rows(Decompose.rows)
            handLocked(true)
            Decompose.root.getKeys(false).filter { it.startsWith("icon-") }.forEach {
                val itemStack = buildItem(Decompose.root.getItemStack(it)!!) {
                    flags += ItemFlag.values()
                }
                Decompose.root.getIntegerList("${it}.slots").forEach { slot ->
                    set(slot, itemStack) {
                        isCancelled = true
                    }
                }
            }
            set(confirm, confirmIcon) {
                isCancelled = true
                if (get) {
                    show.forEach { slot ->
                        back(slot, inventory)
                    }
                    get = false
                    inventory.setItem(confirm, confirmIcon)
                } else {
                    val decomposeItem = inventory.getItem(Decompose.slot) ?: run {
                        viewer.sendLang("things-cannot-decompose")
                        return@set
                    }
                    if (ItemDecomposeEvent.Pre(viewer, decomposeItem).call()) {
                        val slot = decomposeItem.getItemTag()["DECOMPOSE"]?.asList() ?: run {
                            viewer.sendLang("things-cannot-decompose")
                            return@set
                        }
                        inventory.setItem(Decompose.slot, null)
                        var items = 0
                        slot.forEach {
                            val thing = it.asString().split(" ")
                            val item = thing[0]
                            val number = thing[1].toInt()
                            val random = thing[2].toDouble()
                            if (number != 0 && random(random)) {
                                decomposeItems += ItemPlant.build(viewer, item)!!.apply { amount = number }
                                items++
                            }
                        }
                        if (items == 0) {
                            if (default != null) {
                                decomposeItems += ItemPlant.build(viewer, default!!)!!
                            }
                        }
                        if (decomposeItems.isNotEmpty()) {
                            decomposeItems.forEachIndexed { index, itemStack ->
                                inventory.setItem(show[index], itemStack)
                            }
                            inventory.setItem(confirm, getIcon)
                            get = true
                            ItemDecomposeEvent.Post(viewer, decomposeItem, decomposeItems).call()
                            decomposeItems.clear()
                        }
                    }
                }
            }
            onClick {
                it.clickEventOrNull()?.apply {
                    if (click != ClickType.LEFT && click != ClickType.RIGHT) {
                        it.isCancelled = true
                    }
                }
            }
            onBuild { _, _ ->
                decomposeItems.clear()
            }
            onClose {
                show.forEach { slot ->
                    back(slot, it.inventory)
                }
                back(slot, it.inventory)
            }
        }
    }

    fun back(slot: Int, inventory: Inventory) {
        val itemStack = inventory.getItem(slot)
        if (itemStack.isAir()) return
        viewer.giveItem(itemStack)
        inventory.setItem(slot, null)
    }

}